package com.cndw.kungfu.model.battle;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;

import com.cndw.kungfu.config.Constants;
import com.cndw.kungfu.config.ConstantsIntKey;
import com.cndw.kungfu.config.ConstantsRadio;
import com.cndw.kungfu.domain.GoodsMode;
import com.cndw.kungfu.domain.Player;
import com.cndw.kungfu.domain.SkillMode;
import com.cndw.kungfu.exception.NoticeException;
import com.cndw.kungfu.ext.NumberProcesser;
import com.cndw.kungfu.ext.TimeProcesser;
import com.cndw.kungfu.model.Context;
import com.cndw.kungfu.model.battle.buff.BuffLibI;
import com.cndw.kungfu.model.battle.buff.Status1NoAttackBuff;
import com.cndw.kungfu.model.battle.buff.Status2FixTargerBuff;
import com.cndw.kungfu.model.battle.buff.Status3ImmuneBuff;
import com.cndw.kungfu.model.battle.buff.Status6ContinuedBuff;
import com.cndw.kungfu.model.pvp.war.WarFighter;
import com.cndw.kungfu.model.skill.PlayerSkill;
import com.cndw.kungfu.model.skill.SkillGird;
import com.cndw.kungfu.vo.battlevo.ADrugUse;
import com.cndw.kungfu.vo.battlevo.AFailGoodsVO;
import com.cndw.kungfu.vo.battlevo.AHurtVO;
import com.cndw.kungfu.vo.battlevo.AResultVO;
import com.cndw.kungfu.vo.battlevo.ATalkVO;
import com.cndw.kungfu.vo.battlevo.BattleReportVO;
import com.cndw.kungfu.vo.battlevo.BattleWinVO;
import com.cndw.kungfu.vo.battlevo.BuffExecVO;
import com.cndw.kungfu.vo.battlevo.BuffOverVO;

/**
 * 即时战斗瞬间模拟类
 * 
 * @author fantadust [9677889@qq.com]
 * @date 2011-6-16 下午05:39:05
 */
public class Battle {

	private int id;
	private static AtomicInteger signNum = new AtomicInteger(0);

	private final Fighter sourceMaster;
	private final Fighter targetMaster;

	public final Set<Long> sourceIds = new HashSet<Long>(3);
	public final Set<Long> targetIds = new HashSet<Long>(3);
	/**
	 * 所有战斗角色 以下4个集合在战斗中会进行删除成员
	 */
	private final List<Fighter> fightersRun = new ArrayList<Fighter>(6);
	private final List<Fighter> fightersSource = new ArrayList<Fighter>(3);
	private final List<Fighter> fightersTarget = new ArrayList<Fighter>(3);
	private final HashSet<Fighter> fightersRemove = new HashSet<Fighter>(3);
	/**
	 * 所有参加战斗的成员,不删除
	 */
	private final List<Fighter> allFighters = new ArrayList<Fighter>(6);
	private final List<Player> allPlayerFighters = new ArrayList<Player>(6);
	private final List<Fighter> allPets = new ArrayList<Fighter>(6);
	/**
	 * 使用到的技能id
	 */
	private final Map<Integer, Set<Long>> useSkillIds = new HashMap<Integer, Set<Long>>();
	/**
	 * 战力的系数设置
	 */
	private final Map<Long, Integer> buffCoefMap = new HashMap<Long, Integer>();

	private final List<Object> report = new LinkedList<Object>();
	private int winer = 0;// 0 1我胜利 2对手升级

	private int startTime;
	private int costTime;
	/**
	 * 回合数
	 */
	private int round = 0;

	private static final int stepTime = 2;

	private int asset;
	private int exp;
	/**
	 * 战斗类型
	 */
	private int type = 0;
	/**
	 * 物品编号id
	 */
	private int indexId = 0;
	/**
	 * 进攻方伤害血量
	 */
	private int sourceDam;
	/**
	 * 怪物掉落幸运值
	 */
	public int failLuckAdd = 0;
	/**
	 * 免费恢复血量和魔法量
	 */
	private int freeBloodMagic = 0;
	/**
	 * 战斗参数配置
	 */
	private int configType = 0;
	private int configNum = 0;
	private int sceneType = 0;
	/**
	 * 掉率
	 */
	private boolean rateCoef;
	/**
	 * 怪物bossId
	 */
	private int defaultMonsterId = 0;

	private Map<Integer, FailGoods> failGoodsMap;

	private BattleReportVO battleReportVO = new BattleReportVO();

	private List<Integer> deadMonsterId;

	private ScheduledFuture<?> taskFuture;

	private Set<Long> receiveMap = new HashSet<Long>(1);

	/**
	 * 2个玩家(含队伍)进行战斗
	 * 
	 * @param sourcePlayer
	 * @param targetPlayer
	 */
	public Battle(Player sourcePlayer, Player targetPlayer) {
		Team sourceTeam = sourcePlayer.getTeam();
		Team targetTeam = targetPlayer.getTeam();
		if (sourceTeam == null) {
			sourceMaster = sourcePlayer.getLikedFighter();
			fightersSource.add(sourceMaster);
		} else {
			sourceMaster = sourceTeam.getMaster();
			fightersSource.addAll(sourceTeam.getBattleMembers());
		}
		if (targetTeam == null) {
			targetMaster = targetPlayer.getLikedFighter();
			fightersTarget.add(targetMaster);
		} else {
			targetMaster = targetTeam.getMaster();
			fightersTarget.addAll(targetTeam.getBattleMembers());
		}
		initBattle();
	}

	public Battle(WarFighter sourceCross, WarFighter targetCross) {
		sourceMaster = sourceCross.getCrossPlayer();
		fightersSource.add(sourceCross.getCrossPlayer());
		if (sourceCross.getCrossPet() != null) {
			fightersSource.add(sourceCross.getCrossPet());
		}
		targetMaster = targetCross.getCrossPlayer();
		fightersTarget.add(targetCross.getCrossPlayer());
		if (targetCross.getCrossPet() != null) {
			fightersTarget.add(targetCross.getCrossPet());
		}
		initBattle();
	}

	/**
	 * 一个玩家或队伍,战斗1个怪物 此方法删除
	 * 
	 * @param sourcePlayer
	 * @param targetFighter
	 */
	@Deprecated
	public Battle(Player sourcePlayer, Fighter targetFighter) {
		Team sourceTeam = sourcePlayer.getTeam();
		if (sourceTeam == null) {
			sourceMaster = sourcePlayer.getLikedFighter();
			fightersSource.add(sourceMaster);
		} else {
			sourceMaster = sourceTeam.getMaster();
			fightersSource.addAll(sourceTeam.getBattleMembers());
		}
		targetMaster = targetFighter;
		fightersTarget.add(targetFighter);
		initBattle();
	}

	/**
	 * 单个战斗对象,不引入队员
	 * 
	 * @param sourceFighter
	 * @param targetFighter
	 */
	public Battle(Fighter sourceFighter, Fighter targetFighter) {
		sourceMaster = sourceFighter;
		fightersSource.add(sourceFighter);
		targetMaster = targetFighter;
		fightersTarget.add(targetFighter);
		initBattle();
	}

	/**
	 * 一个玩家或队伍,战斗一群怪物
	 * 
	 * @param sourcePlayer
	 * @param targetFighters
	 */
	public Battle(Player sourcePlayer, Collection<FighterMonster> targetFighters, int defaultMonsterId) {
		Team sourceTeam = sourcePlayer.getTeam();
		if (sourceTeam == null) {
			sourceMaster = sourcePlayer.getLikedFighter();
			fightersSource.add(sourceMaster);
		} else {
			sourceMaster = sourceTeam.getMaster();
			fightersSource.addAll(sourceTeam.getBattleMembers());
		}
		fightersTarget.addAll(targetFighters);
		if (targetFighters.size() == 1) {
			targetMaster = fightersTarget.get(0);
		} else {
			Fighter tempFighter = null;
			for (FighterMonster e : targetFighters) {
				if (e.getSourceObject().getId() == defaultMonsterId) {
					tempFighter = e;
					break;
				}
			}
			if (tempFighter == null) {
				tempFighter = fightersTarget.get(0);
			}
			targetMaster = tempFighter;
		}

		this.defaultMonsterId = defaultMonsterId;
		initBattle();
	}

	public Battle(Fighter sourceFighter, Collection<FighterMonster> targetFighters, int defaultMonsterId) {
		sourceMaster = sourceFighter;
		fightersSource.add(sourceMaster);
		fightersTarget.addAll(targetFighters);
		if (targetFighters.size() == 1) {
			targetMaster = fightersTarget.get(0);
		} else {
			Fighter tempFighter = null;
			for (FighterMonster e : targetFighters) {
				if (e.getSourceObject().getId() == defaultMonsterId) {
					tempFighter = e;
					break;
				}
			}
			if (tempFighter == null) {
				tempFighter = fightersTarget.get(0);
			}
			targetMaster = tempFighter;
		}
		this.defaultMonsterId = defaultMonsterId;
		initBattle();
	}

	public Battle(FighterTeam sourceTeam, FighterTeam targetTeam) {
		fightersSource.addAll(sourceTeam.getBattleMembers());
		fightersTarget.addAll(targetTeam.getBattleMembers());
		sourceMaster = sourceTeam.getMaster();
		targetMaster = targetTeam.getMaster();
		initBattle();
	}

	public void setDefaultMonsterId(int defaultMonsterId) {
		this.defaultMonsterId = defaultMonsterId;
	}

	private void buffCoefSet(long playerId, int coef) {
		buffCoefMap.put(playerId, coef);
	}

	private int buffCoefGet(long playerId) {
		if (!buffCoefMap.containsKey(playerId)) {
			return 0;
		}
		return buffCoefMap.get(playerId);
	}

	/**
	 * 初始化化运算基本数据 运行周期等
	 */
	private void initBattle() {

		fightersRun.addAll(fightersSource);
		fightersRun.addAll(fightersTarget);

		allFighters.addAll(fightersRun);

		id = signNum.incrementAndGet();

		Context.getDataServer().getBattleMap().put(id, this);

		for (Fighter e : fightersSource) {
			sourceIds.add(e.getUniqueId());
			battleReportVO.getSourceMemberVOs().add(e.toVO());
			Object ee = e.getSourceObject();
			if (ee instanceof Player) {
				allPlayerFighters.add((Player) ee);
			}
			if (e.getBuffCoefficient() != 0) {
				buffCoefSet(e.getUniqueId(), e.getBuffCoefficient());
			}
		}
		for (Fighter e : fightersTarget) {
			targetIds.add(e.getUniqueId());
			battleReportVO.getTargetMemberVOs().add(e.toVO());
			Object ee = e.getSourceObject();
			if (ee instanceof Player) {
				allPlayerFighters.add((Player) ee);
			} else if (e instanceof FighterMonster) {// 怪物初始化ai动作
				((FighterMonster) e).aiSignSet(0);
			}
			if (e.getBuffCoefficient() != 0) {
				buffCoefSet(e.getUniqueId(), e.getBuffCoefficient());
			}
		}

		for (Player e : allPlayerFighters) {// 对角色增加宠物战斗素材
			Fighter pet = e.getLikedFighterPet(buffCoefGet(e.getPlayerId()));

			if (pet != null) {
				allPets.add(pet);

				if (pet.getHp() <= 0) {
					pet.alterHp(1);
				}
				fightersRun.add(pet);
				if (sourceIds.contains(e.getPlayerId())) {
					sourceIds.add(pet.getUniqueId());
					fightersSource.add(pet);
					battleReportVO.getSourceMemberVOs().add(pet.toVO());
				} else {
					targetIds.add(pet.getUniqueId());
					fightersTarget.add(pet);
					battleReportVO.getTargetMemberVOs().add(pet.toVO());
				}
			}
		}

		// 按照攻速排序战斗对象
		FighterComparator c = new FighterComparator();
		Collections.sort(fightersRun, c);

		for (Player e : allPlayerFighters) {
			PlayerSkill playerSkill = Context.getSkillServer().getPlayerSkill(e.getPlayerId());
			if (playerSkill != null) {
				playerSkill.setLastGirdId(0);// 初始化技能开始id
				playerSkill.clacLastTimes();// 清理技能cd

			}
		}

	}

	public void config(int configType, int sceneType, int configNum) {
		if (configType == 1) {// 世界boss
			freeBloodMagic = 1;
		}
		this.configType = configType;
		this.sceneType = sceneType;
		this.configNum = configNum;
	}

	public void execBattle(int battleType) {
		type = battleType;
		startTime = TimeProcesser.getUnixTime();
		boolean isend = false;
		int roundMax = battleType == Constants.battle_pvpCross ? 300 : 30;
		while (!isend) {
			round++;
			if (fightersRun.isEmpty() == false) {
				for (Fighter source : fightersRun) {
					if (source.getHp() <= 0) {
						continue;
					}
					try {
						AResultVO resultVO = attack(source);
						if (resultVO != null) {
							report.add(resultVO);// 添加到战报里面
						}
						if (winer > 0) {
							break;
						}

					} catch (Exception e) {
						e.printStackTrace();
					}
				}

				execBuff(round);

				if (fightersRemove.size() > 0) {
					fightersRun.removeAll(fightersRemove);
					fightersRemove.clear();
				}

			}
			if (winer > 0) {
				break;
			} else if (round >= roundMax) {
				break;
			}
		}
		if (type == Constants.battle_pvp || type == Constants.battle_livery || type == Constants.battle_siege || type == Constants.battle_pvpNoCost) {// pvp战斗不使用续命包

		} else {
			for (Player e : allPlayerFighters) {
				if (freeBloodMagic == 1) {// 免费恢复血量/不使用续命包
					e.setHp(e.getMaxHp());
					e.setMp(e.getMaxMp());
					if (e.getDataInfo().getPet() != null) {
						e.getDataInfo().getPet().fullHpMp();
					}
				} else {
					e.useBloodMagicBag();
					if (e.getDataInfo().intDataGet(ConstantsIntKey.aPetBag) == 1 && e.getDataInfo().getPet() != null) {
						e.getDataInfo().getPet().useBloodMagicBag();
					}
				}

			}
		}
		for (Fighter e : allPets) {
			if (e.getHp() <= 0) {
				e.alterHp(1);
			}
		}

		for (Fighter e : allFighters) {
			e.alterFixAttack(0);// 清理buff数据 攻击者
			e.alterFixCrit(0);
			e.alterFixDefense(0);
			e.alterFixDodge(0);
			e.alterFixHit(0);
			e.alterFixTough(0);
		}

		if (winer == 1 || configType == 1) {// 赢了 或者是世界boss 都可以领取
			BattleOnDead.FailByFighterList(this, allFighters);
		}

		syncReport();// 同步战报信息

		endTask();
	}

	public void deployReport(int deployId) {
		battleReportVO.setDeployId(deployId);
	}

	private void syncReport() {
		battleReportVO.setStartTime(startTime);
		battleReportVO.setEndTime(costTime + startTime);
		battleReportVO.setStepTime(stepTime);
		battleReportVO.setAsset(asset);
		battleReportVO.setExp(exp);
		battleReportVO.setReport(report);
		battleReportVO.setWiner(winer);
		battleReportVO.setType(type);

		battleReportVO.setSourceMasterId(sourceMaster.getUniqueId());
		battleReportVO.setTargetMasterId(targetMaster.getUniqueId());

		if (!useSkillIds.isEmpty()) {
			for (int skillId : useSkillIds.keySet()) {
				SkillMode skillMode = Context.getSkillServer().getSkillMode(skillId);
				battleReportVO.addSkillVO(skillMode.toBattleSkillVO());
			}
			battleReportVO.setUseSkillIds(useSkillIds);

		}

		if (winer > 0) {
			BattleWinVO winVO = new BattleWinVO(winer == 1 ? sourceMaster.getUniqueId() : targetMaster.getUniqueId());
			battleReportVO.setWinVO(winVO);
		}
		if (failGoodsMap != null && !failGoodsMap.isEmpty()) {
			List<AFailGoodsVO> failGoodsVOs = new ArrayList<AFailGoodsVO>();
			int failIndexId = NumberProcesser.mtRand(allPlayerFighters.size()) - 1;
			for (FailGoods e : failGoodsMap.values()) {
				if (e.getPlayerId() == 0) {
					e.setPlayerId(allPlayerFighters.get(failIndexId).getPlayerId());
					failIndexId++;
					if (failIndexId == allPlayerFighters.size()) {
						failIndexId = 0;
					}
				}

				failGoodsVOs.add(e.toVO());
			}
			battleReportVO.setFailGoodsList(failGoodsVOs);
		}

	}

	private void addSkill(int currentSkillId, long figterId) {
		if (!useSkillIds.containsKey(currentSkillId)) {
			useSkillIds.put(currentSkillId, new HashSet<Long>());
		}
		useSkillIds.get(currentSkillId).add(figterId);
	}

	private AResultVO attack(final Fighter source) throws Exception {

		int defaultSkillLibId = 1000000;
		if (source.getHp() <= 0) {
			return null;
		}

		if (!source.getBuffMap().isEmpty()) {
			for (BuffLibI e : source.getBuffMap().values()) {
				if (e instanceof Status1NoAttackBuff) {
					if (((Status1NoAttackBuff) e).isNoAttack()) {// 暂时不能攻击
						throw new NoticeException("You are prohibited to attack");
					}
				}
			}
		}
		/**
		 * 获得技能
		 */

		int position = 0;
		int currentSkillId = defaultSkillLibId;
		if (source instanceof ISkillGird) {
			SkillGird skillGird = ((ISkillGird) source).getSkillGird(round);
			if (skillGird != null) {
				position = skillGird.getPosition();
				if (skillGird.isAreGoods()) {// 在获取技能的时候已把物品消耗掉
					GoodsMode goodsMode = Context.getGoodsServer().getModeById(skillGird.getId());
					if (goodsMode == null || goodsMode.getAppId() != Constants.Goods_App_Drug) {
						return null;
					}
					source.alterHp(goodsMode.getValueA());
					source.alterMp(goodsMode.getValueB());

					ADrugUse aDrugUse = new ADrugUse();
					aDrugUse.setU(source.getUniqueId());
					aDrugUse.setgId(skillGird.getId());
					aDrugUse.setP(skillGird.getPosition());

					aDrugUse.setH(goodsMode.getValueA());
					aDrugUse.setM(goodsMode.getValueB());

					aDrugUse.setHp(source.getHp());
					aDrugUse.setMp(source.getMp());
					aDrugUse.setT(round);
					report.add(aDrugUse);
					costTime += 2;

					// 加血
					return null;
				} else {
					currentSkillId = skillGird.getId();
				}
			}

		} else if (source instanceof FighterMonster) {
			// 怪物ai.说话或者技能
			List<AiAction> aiActions = ((FighterMonster) source).getAiActions();
			if (aiActions != null) {
				boolean isOk = false;
				for (AiAction ai : aiActions) {
					if (((FighterMonster) source).isSignAi(ai.getAid()) == false) {

						switch (ai.getAt()) {
						case AiAction.typeHp:
							isOk = source.getHp() * 100 / source.getMaxHp() <= ai.getAtv();
							break;
						case AiAction.typeRound:
							isOk = round == ai.getAtv();
							break;
						case AiAction.typeRate:
							isOk = NumberProcesser.isWinning(ai.getAtv());
							break;
						default:
							break;
						}
						if (isOk) {// 添加标记
							if (ai.getAt() != AiAction.typeRate) {
								((FighterMonster) source).aiSignAdd(ai.getAid());
							}

							if (ai.getAct() == AiAction.typeAtvTalk) {

								ATalkVO aTalkVO = new ATalkVO();
								aTalkVO.setU(source.getUniqueId());
								aTalkVO.setS(ai.getActv());
								aTalkVO.setT(round);
								report.add(aTalkVO);

							} else if (ai.getAct() == AiAction.typeAtvSkill) {
								SkillMode aiSkillMode = Context.getSkillServer().getSkillMode(ai.getActid());
								if (aiSkillMode != null && source.getMp() >= aiSkillMode.getConstMp()) {
									currentSkillId = aiSkillMode.getId();
								}
							}
							break;// 跳出
						}
					}
				}
			}

		} else if (source instanceof ISkill) {
			currentSkillId = ((ISkill) source).getCurrentSkillId(round);
		}
		currentSkillId = currentSkillId == 0 ? defaultSkillLibId : currentSkillId;
		SkillMode skillMode = Context.getSkillServer().getSkillMode(currentSkillId);
		if (skillMode == null) {
			return null;
		}
		addSkill(currentSkillId, source.getUniqueId());

		costTime += skillMode.getPlayTime();

		// 攻击者消耗魔法值
		source.alterMp(-skillMode.getConstMp());

		boolean isSkillAddBlood = skillMode.getPassiveType() == Constants.skillAddBlood;
		Fighter target = null;

		if (!isSkillAddBlood) {

			if (source.getBuffMap().isEmpty() == false) {
				for (BuffLibI e : source.getBuffMap().values()) {
					if (e instanceof Status2FixTargerBuff) {
						target = ((Status2FixTargerBuff) e).fixTarger();
					}
				}
			}

		}

		List<AHurtVO> targerDTO = new ArrayList<AHurtVO>();
		if (target == null) {
			List<Fighter> targetfFighters = getTargets(source, skillMode);
			int targetNums = targetfFighters.size();
			if (targetNums == 1) {
				target = targetfFighters.get(0);
			} else {
				// Collections.shuffle(targetfFighters);
				int attackNums = skillMode.getGroupNum() > 0 ? skillMode.getGroupNum() : 1;
				if (attackNums == 1) {
					int indexId = NumberProcesser.mtRand(targetNums) - 1;
					target = targetfFighters.get(indexId);
				} else {
					attackNums = attackNums > targetNums ? targetNums : attackNums;
					List<Fighter> currenFighters = new ArrayList<Fighter>();
					for (int i = indexId; i < attackNums; i++) {
						currenFighters.add(targetfFighters.get(i));
					}
					for (Fighter targetFighter : currenFighters) {
						AHurtVO rs = oneAttack(source, targetFighter, skillMode);
						targerDTO.add(rs);
					}
				}
			}

		}
		if (target != null) {
			AHurtVO rs = oneAttack(source, target, skillMode);
			targerDTO.add(rs);
		}

		AHurtVO sourceDto = new AHurtVO(source.getUniqueId(), 0, 0, source.getHp(), source.getMp());

		checkDeath(source);// 判断结束

		AResultVO resultVO = new AResultVO(skillMode.getId(), position);
		resultVO.setS(sourceDto);
		resultVO.setH(targerDTO);
		resultVO.setT(round);
		return resultVO;
	}

	private AHurtVO oneAttack(Fighter source, Fighter target, SkillMode skillMode) {
		int dam = 0;
		int s1 = 0, t1 = 0, t2 = 0;
		int attactType = AHurtVO.TYPE_NORMAL;
		if (skillMode.getPassiveType() == Constants.skillAddBlood) {
			dam = NumberProcesser.percentOnlyAddValue(source.getAttack(), skillMode.getEffectValue());
			target.alterHp(dam);
		} else {
			boolean isImmune = false;
			for (BuffLibI e : target.getBuffMap().values()) {
				if (e instanceof Status3ImmuneBuff) {
					if (((Status3ImmuneBuff) e).isImmune(skillMode)) {
						isImmune = true;// 免疫了
						break;
					}
				}
			}
			if (isImmune) {// 免疫
				attactType = AHurtVO.TYPE_IMMUNE;
			} else {

				boolean isHit = BattleFormula.checkHit(source, target);
				if (isHit == false) {
					attactType = AHurtVO.TYPE_MISS;
				} else {

					float damf = BattleFormula.clacHurt(source, target, skillMode.getEffectValue());

					boolean isCrit = BattleFormula.checkCrit(source, target);
					if (isCrit) {
						attactType = AHurtVO.TYPE_CRIT;
						damf = damf * 2;
					}

					// 会心一击
					// if (source instanceof FighterPlayer) {
					// Player sourcePlayer = (Player) source.getSourceObject();
					// if (sourcePlayer.getDataInfo().isHavedLuck()) {
					// if (NumberProcesser.isWinning(5)) {
					// damf = damf * 3 / 2;
					// attactType = attactType | AHurtVO.TYPE_LUCKY;
					// }
					// }
					// }
					s1 = source.getHurtAbsorb();// 傷害吸收
					t1 = target.getHurtRemove();// 傷害減免
					t2 = target.getHurtReflex();// 傷害反射

					if (skillMode.getPassiveType() == Constants.skillGotBlood) {
						s1 = skillMode.getPassiveValue();
					} else if (skillMode.getPassiveType() == Constants.skillGotMagic) {
						source.alterMp(skillMode.getPassiveValue());
						target.alterMp(-skillMode.getPassiveValue());
					}

					damf += source.getHurtAdd();// 傷害追加
					damf -= t1;// 傷害減免

					source.alterHp(s1 - t2);
					if (isCrit) {
						damf += source.getCritAdd();// 暴擊追加
					}
					if (Constants.isPvpType(type)) {// 伤害比加成
						int damCoff = source.getHurtCoffAdd() - target.getHurtCoffRemove();
						if (damCoff != 0) {
							damf = damf * (1 + damCoff / 1000f);
						}
					}

					damf = damf <= 0 ? 1 : damf;
					if (sourceIds.contains(source.getUniqueId())) {
						sourceDam += damf > target.getHp() ? target.getHp() : damf;
					}

					dam = 0 - Float.valueOf(damf).intValue();
					target.alterHp(dam);
					checkDeath(target);// 判断结束
				}

			}
		}

		AHurtVO rs = new AHurtVO(target.getUniqueId(), dam, attactType, target.getHp(), target.getMp());
		rs.setS1(s1);
		rs.setT1(t1);
		rs.setT2(t2);

		if (skillMode.getBuffId() > 0 && NumberProcesser.isWinning(skillMode.getBuffRate())) {
			// buff的触发编写
			// BuffLibI buff = BuffInvoke.invoke(skillMode.getBuffId(), source,
			// target, this);

		}
		return rs;
	}

	private boolean checkDeath(Fighter fighter) {
		if (fighter.getHp() <= 0) {
			fightersRemove.add(fighter);
			if (sourceIds.contains(fighter.getUniqueId())) {
				fightersSource.remove(fighter);
			} else {
				fightersTarget.remove(fighter);
			}
			// FighterOnDead.onDead(fighter, this);// 死亡掉落等外部处理

			checkEnd();
			return true;
		}
		return false;
	}

	private void checkEnd() {
		if (winer == 0) {
			if (fightersSource.size() == 0) {
				winer = 2;
			} else if (fightersTarget.size() == 0) {
				winer = 1;
			}
		}
	}

	private List<Fighter> getTargets(Fighter source, SkillMode skillMode) throws Exception {
		boolean isSource = false;
		boolean isOwner = skillMode.getTargetType() == 2;
		if (sourceIds.contains(source.getUniqueId())) {
			isSource = true;
		}
		List<Fighter> targerList = fightersTarget;
		if ((isSource == true && isOwner) || (isSource == false && isOwner == false)) {
			targerList = fightersSource;
		}
		if (targerList.size() == 0) {
			throw new NoticeException("no this target");
		}
		return targerList;
	}

	private void execBuff(int k) {
		// 遍历持续性buff
		for (Fighter fighter : fightersRun) {
			for (BuffLibI e : fighter.getBuffMap().values()) {
				boolean isOver = e.checkOver();
				if (isOver) {
					report.add(new BuffOverVO(e.getSignId(), e.getTarget().getUniqueId()));
				} else if (e instanceof Status6ContinuedBuff) {
					BuffExecVO buffexec = ((Status6ContinuedBuff) e).runRound();
					if (buffexec != null) {
						report.add(buffexec);
					}
				}
			}
		}

	}

	public void addDeadMonsterId(int monsterId) {
		if (deadMonsterId == null) {
			deadMonsterId = new ArrayList<Integer>();
		}
		deadMonsterId.add(monsterId);
	}

	public void addFailGoods(long mId, int goodsId, long playerId) {
		addFailGoods(mId, goodsId, playerId, 0);
	}

	public void addFailGoods(long mId, int goodsId, long playerId, int bind) {

		FailGoods failGoods = new FailGoods(mId, goodsId, bind);

		if (playerId == 0 && allPlayerFighters.size() == 1) {
			playerId = sourceMaster.getUniqueId();
		}
		indexId++;
		failGoods.setIndexId(indexId);
		failGoods.setPlayerId(playerId);

		if (failGoodsMap == null) {
			failGoodsMap = new ConcurrentHashMap<Integer, FailGoods>();
		}
		failGoodsMap.put(failGoods.getIndexId(), failGoods);
	}

	public void setAssetAndExp(int asset, int exp) {
		this.asset = asset;
		this.exp = exp;
	}

	/**
	 * 战报推送
	 */
	public void broadcast() {
		for (Player player : allPlayerFighters) {
			broadcast(player);
		}
	}

	public void broadcast(Player player) {
		Context.getTcpServer().broadcast(battleReportVO, ConstantsRadio.battle, player.getPlayerId());
	}

	private void endTask() {

		Runnable r = new Runnable() {

			@Override
			public void run() {

				for (Player e : allPlayerFighters) {
					e.useBloodMagicBag();
					if (deadMonsterId != null && !deadMonsterId.isEmpty()) {
						Context.getTaskServer().killMonsterToTask(e.getPlayerId(), deadMonsterId);
					}
				}

			}
		};

		taskFuture = Context.getTimerServer().scheduleSeconds(r, costTime);

	}

	/**
	 * 从内存里面删除战报
	 */
	public void clear() {
		if (taskFuture != null) {
			taskFuture.cancel(false);
		}
		Context.getDataServer().getBattleMap().remove(id);
	}

	public boolean isAllReceive() {
		return receiveMap.size() == allPlayerFighters.size();
	}

	public synchronized void signReceive(long playerId) {
		receiveMap.add(playerId);
	}

	public synchronized boolean isReceive(long playerId) {
		return receiveMap.contains(playerId);
	}

	public int getId() {
		return id;
	}

	public int getType() {
		return type;
	}

	public int getAsset() {
		return asset;
	}

	public int getExp() {
		return exp;
	}

	public int getCostTime() {
		return costTime;
	}

	public int getEndTime() {
		return startTime + costTime;
	}

	public Map<Integer, FailGoods> getFailGoodsMap() {
		return failGoodsMap;
	}

	public int getWiner() {
		return winer;
	}

	public int getSourceDam() {
		return sourceDam;
	}

	public String getTargetMasterName() {
		return targetMaster.getName();
	}

	public BattleReportVO getBattleReport() {
		return battleReportVO;
	}

	public Collection<Player> getAllPlayers() {
		return allPlayerFighters;
	}

	public int getDefaultMonsterId() {
		return defaultMonsterId;
	}

	public int getRound() {
		return round;
	}

	public int getConfigType() {
		return configType;
	}

	public int getConfigNum() {
		return configNum;
	}

	public int getSceneType() {
		return sceneType;
	}

	public Fighter getSourceMaster() {
		return sourceMaster;
	}

	public boolean isRateCoef() {
		return rateCoef;
	}

	public void setRateCoef(boolean rateCoef) {
		this.rateCoef = rateCoef;
	}

}
